// 导出一个函数，用来生成XOR问题的训练数据
export function getData(numSamples) {
    // 用来存储所有生成的数据点
    let points = [];

    // 内部函数：生成围绕某个中心点的高斯分布数据
    function genGauss(cx, cy, label) {
      // 为每个中心点生成numSamples/2个点
      for (let i = 0; i < numSamples / 2; i++) {
        // 生成x坐标，围绕cx的正态分布
        let x = normalRandom(cx);
        // 生成y坐标，围绕cy的正态分布  
        let y = normalRandom(cy);
        // 将生成的点（包含坐标和标签）添加到数组中
        points.push({ x, y, label });
      }
    }

    // 生成4个高斯分布的点集，构成XOR模式
    // 右上和左下的点集标记为0
    genGauss(2, 2, 0);    // 右上区域的点，标签0
    genGauss(-2, -2, 0);  // 左下区域的点，标签0
    // 左上和右下的点集标记为1
    genGauss(-2, 2, 1);   // 左上区域的点，标签1
    genGauss(2, -2, 1);   // 右下区域的点，标签1
    // 返回生成的所有数据点
    return points;
  }

  /**
   * 生成符合正态分布的随机数
   * 使用Box-Muller变换算法将均匀分布转换为正态分布
   * 
   * @param mean 均值，默认是0
   * @param variance 方差，默认是1
   */
  function normalRandom(mean = 0, variance = 1) {
    let v1, v2, s;
    // Box-Muller变换：首先生成两个在[-1,1]之间的均匀分布随机数
    do {
      v1 = 2 * Math.random() - 1;  // v1范围: [-1,1]
      v2 = 2 * Math.random() - 1;  // v2范围: [-1,1]
      s = v1 * v1 + v2 * v2;       // 计算s值，用于后续判断
    } while (s > 1);  // 只使用单位圆内的点(s ≤ 1)

    // 使用Box-Muller公式计算符合标准正态分布的随机数
    let result = Math.sqrt(-2 * Math.log(s) / s) * v1;
    // 调整均值和方差，返回最终结果
    return mean + Math.sqrt(variance) * result;
  }

  // 举个例子：当调用getData(4)时，输出大概是这样的（具体数值会有随机波动）：
  /*
  [
    { x: 约2附近, y: 约2附近, label: 0 },
    { x: 约2附近, y: 约2附近, label: 0 },  // 右上区域的2个点
    { x: 约-2附近, y: 约-2附近, label: 0 },
    { x: 约-2附近, y: 约-2附近, label: 0 },  // 左下区域的2个点
    { x: 约-2附近, y: 约2附近, label: 1 },
    { x: 约-2附近, y: 约2附近, label: 1 },  // 左上区域的2个点
    { x: 约2附近, y: 约-2附近, label: 1 },
    { x: 约2附近, y: 约-2附近, label: 1 }   // 右下区域的2个点
  ]
  */
  
  // 这个数据集之所以叫XOR问题，是因为如果把坐标看作输入，标签看作输出，
  // 它符合XOR逻辑：当两个输入同号(都正或都负)时输出0，异号时输出1
  // 这种模式无法用简单的线性模型分开，必须使用神经网络等非线性模型